<?php
class Core_Model_FullPathCatalog implements Core_Model_ICatalog
{
	const ROOT_PATH = 1;
	const ROOT_LEVEL = 1;
	
	protected $_name = 'catalog';
	
	protected $_treeData = array();
	
	protected $_rootNode = null;
	
	protected $dbAdapter = null;
	
	protected $_data = array();
	
	protected $_selectFields = array( '*' );
	
	protected $_whereStatement = '1=1';

	public function __construct( $inputData = null ) {
		/*if ( is_numeric( $inputData ) )
		{
			$this->_initDBAdapter();
			$this->init( $inputData );
		} else*/if ( is_array( $inputData ) )
		{
			if ( !empty ( $inputData['data'] ) ) {
				$this->_data = $inputData['data'];
			}
			if ( !empty ( $inputData['rootObj'] ) && ( $inputData['rootObj'] instanceof Core_Model_ICatalog ) ) {
				$this->_rootNode = $inputData['rootObj'];
			}
		} 
		else/*if( is_null( $inputData ) )*/ {
			$this->_initDBAdapter();
		}
	}
	
	private function _initDBAdapter()
	{
		$this->dbAdapter = new Core_Common_DBTable();
		$this->dbAdapter->setOptions( array( Core_Common_DBTable::NAME => $this->_name ) );
	}

	public function insert( $data = array() ) {
		if ( empty( $data['parent_id'] ) && empty( $data['parent_path'] ) ) 
		{
			if ( !($rootId = $this->getRoot() ) ) 
			{
				$rootData['path'] = self::ROOT_PATH;
				$rootData['title'] = 'root';
				$rootData['level'] = self::ROOT_LEVEL;
				$rootData['parent_id'] = 0;
				$this->dbAdapter->insert( $rootData );
			} else {
				throw new Exception( 'No parent node and tree not empty', CATALOG_NO_ROOT);
			}
		} else {
			$this->prepareData( $data );
			$this->dbAdapter->insert( $data );
		}
	}
	
	public function update( $data = array() )
	{
		if ( !empty ( $data['id'] ) )
		{
			$where = $this->dbAdapter->getAdapter()->quoteInto('id = ?', $data['id']);
			$this->dbAdapter->update( $data, $where );
		}
	}


	public function delete( $parentId )
	{
		if ( $parentId )
		{
			$rootNode = $this->getNodeById( $parentId );
			if ( !empty ($rootNode) ){
				$this->dbAdapter->delete( 'path like "'.$rootNode->path.'%"' );
			}
		}
	}

	protected function prepareData( &$data )
	{
		$parentNode = $this->getNodeById( $data['parent_id'] );
		$data['level'] = $parentNode->level + 1;
		$lastSibling = $this->getLastSibling( $parentNode->path, $parentNode->level );
		if ( !empty ( $lastSibling ) )
		{
		   $lastSiblingPathArr = explode( '.', $lastSibling->path );
		   $lastSiblingPathArr[sizeof($lastSiblingPathArr) - 1]++;
		   $data['path'] = implode( '.', $lastSiblingPathArr );
		} else {
		   $data['path'] = $parentNode->path . '.1';
		}
	}
	
   public function getNodeById( $id )
   {
      $return = null;
      $select = $this->dbAdapter->select()->from( 
				  $this->_name, 
				  $this->_selectFields
				 )->where( "id = ?", $id );
      $result = $this->dbAdapter->fetchRow( $select );
      if ( $result ) {
	    $return = new self( array( 'data' => $result->toArray() ) );
      }
      return $return;
   }

	public function getRoot()
	{
	$return = array();
	$select = $this->dbAdapter->select()->from( $this->_name, $this->_selectFields )->order( 'id ASC' )->limit( 1 );
	$result = $this->dbAdapter->fetchRow( $select );
	if ( !empty( $result ) ) {
		$return = new self( array( 'data' => $result->toArray() ) );
	}
	return $return;
	}

   protected function getLastSibling( $parentPath = self::ROOT_PAT, $parentLevel = self::ROOT_LEVEL )
   {
      $return = null;
      $select = $this->dbAdapter->select()->from( $this->_name, $this->_selectFields )->where( "path like '".$parentPath."%' and level = ?", $parentLevel+1 )->order( 'path DESC' )->limit( 1 );
      $result = $this->dbAdapter->fetchRow( $select );
      if ( $result ) {
         $return = new self( array( 'data' => $result->toArray() ) );
      }
      return $return;
   }
	
	public function initTree( $root = 0 )
	{
    	$select = $this->dbAdapter->select()
				  ->from( $this->_name, $this->_selectFields )
					->order( 'path ASC' )
					->where( $this->_whereStatement );
		//echo $select->__toString(); exit;
		if ( $root ){
			$rootNode = $this->getNodeById( $root );
			if ( !empty ($rootNode) ){
				$select->where( 'path like "'.$rootNode->path.'%"' );
			}
		}
//		$select->where( new Zend_Db_Expr( "AES_DECRYPT(title_enc, '456') like '%назван%' " ) );
		
//echo $select->__toString();
    	$result = $this->dbAdapter->fetchAll( $select );
//echo '<xmp>'.print_r($result, 1).'</xmp>'; exit;
		$cntr = 0;
		foreach ( $result as $row )
		{
//echo '<xmp>'.print_r($row->toArray(), 1).'</xmp>'; exit;
			if ( !$cntr ){
				$this->_data = $row->toArray();
			} 
			else {
				$this->_treeData[$row->path] = $row->toArray();
			}
			++$cntr;
		}
	}
	
	public function __get( $attrName )
	{
		return ( !empty ( $this->_data[$attrName] ) ) ? $this->_data[$attrName] : null;
	}

	public function getPlainTree()
	{
		$return = array();
		$return[0] = $this;
		foreach ( $this->_treeData as $treeNode )
		{
			$return[] = new self( array( 'data' => $treeNode, 'rootObj' => $this ) );
		}
		return $return;
	}
	
	public function toArray()
	{
		return ( !empty ( $this->_data ) ) ? $this->_data : array();
	}
/*	
	public function getFieldsMetaData()
	{
		$return = array();
		$return = $this->dbAdapter->info();
		$return = $return['metadata'];
		return $return;
	}
  */
	
	public function setSelectFields( $fields = array() )
	{
		$this->_selectFields = array_merge( $this->_selectFields, $fields );
	}
	
	public function setWhere( $whereStr = '' )
	{
		$this->_whereStatement = $whereStr;
	}
	
}